﻿using System;
using System.Linq.Expressions;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet;

namespace AsNum.Common.EntLib.Extends {
    public static class ValidatorHelper {

        public static BaseValidator AddValidatorFor<T>(this Control control , Expression<Func<T , object>> property) {
            return AddValidatorFor<T> ( control , property , string.Empty );
        }

        public static BaseValidator AddValidatorFor<T>(this Control control , Expression<Func<T , object>> property , string rulesetName) {
            var validator = CreateValidatorFor ( control , property , rulesetName );
            AddValidatorToPageJustAfterControl ( validator , control );
            return validator;
        }

        public static BaseValidator CreateValidatorFor<T>(this Control control , Expression<Func<T , object>> property) {
            return CreateValidatorFor ( control , property , string.Empty );
        }

        public static BaseValidator CreateValidatorFor<T>(this Control control , Expression<Func<T , object>> property , string rulesetName) {
            PropertyProxyValidator proxy = CreateNewProxyValidator ( );
            proxy.ControlToValidate = control.ID;
            BindProxyValidatorToDomainProperty ( proxy , property , rulesetName );
            return proxy;
        }

        private static PropertyProxyValidator CreateNewProxyValidator() {
            return new PropertyProxyValidator ( ) {
                Display = ValidatorDisplay.Static ,
            };
        }

        private static void BindProxyValidatorToDomainProperty<T>(
            PropertyProxyValidator proxy ,
            Expression<Func<T , object>> property , string rulesetName) {
            proxy.PropertyName = GetPropertyName ( property );
            proxy.SourceTypeName = typeof ( T ).AssemblyQualifiedName;
            proxy.RulesetName = rulesetName;
        }

        private static string GetPropertyName(LambdaExpression property) {
            var member = property.Body as MemberExpression;
            if ( member == null ) {
                var unaryExpression = ( UnaryExpression )property.Body;
                member = ( MemberExpression )unaryExpression.Operand;
            }

            return member.Member.Name;
        }

        private static void AddValidatorToPageJustAfterControl(BaseValidator proxy , Control control) {
            int index = control.Parent.Controls.IndexOf ( control );
            control.Parent.Controls.AddAt ( index + 1 , proxy );
        }

    }
}
